<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Peaks.js Demo Page</title>
    <style>
      body {
        font-family: 'Helvetica neue', Helvetica, Arial, sans-serif;
      }

      #titles, #waveform-container {
        margin: 24px auto;
        width: 1000px;
      }

      #zoomview-container, #overview-container {
        box-shadow: 3px 3px 20px #919191;
        margin: 0 0 24px 0;
        -moz-box-shadow: 3px 3px 20px #919191;
        -webkit-box-shadow: 3px 3px 20px #919191;
        line-height: 0;
      }

      #zoomview-container {
        height: 200px;
      }

      #overview-container {
        height: 85px;
      }

      #demo-controls {
        margin: 0 auto 24px auto;
        width: 1000px;
        display: flex;
        align-items: center;
      }

      #demo-controls button {
        background: #fff;
        border: 1px solid #919191;
        cursor: pointer;
      }

      #audio {
        flex: 0 0 30%;
      }

      #controls {
        flex: 1;
        margin-left: 1em;
      }

      #seek-time {
        width: 4em;
      }

      .log {
        margin: 0 auto 24px auto;
        width: 1000px;
      }

      table {
        width: 100%;
      }

      table th {
        text-align: left;
      }

      table th, table td {
        padding: 0.5em;
      }

      .hide {
        display: none;
      }
    </style>
  </head>
  <body>
    <div id="titles">
      <h1>Peaks.js</h1>
      <p>
        Peaks.js is a JavaScript library that allows you to display and
        interaction with audio waveforms in the browser.
      </p>
      <p>
        It was developed by <a href="https://www.bbc.co.uk/rd">BBC R&amp;D</a>
        to allow audio editors to make accurate clippings of audio content.
        You can read more about the project
        <a href="https://waveform.prototyping.bbc.co.uk/">here</a>.
      </p>

      <h2>Demo pages</h2>
      <p>
        The following pages demonstrate various configuration options:
      </p>
      <p>
        <a href="index.html">Precomputed Waveform Data</a> |
        Web Audio API |
        <a href="zoomable-waveform.html">Single Zoomable Waveform</a> |
        <a href="overview-waveform.html">Single Fixed Waveform</a> |
        <a href="cue-events.html">Cue Events</a> |
        <a href="set-source.html">Changing the Media URL</a> |
        <a href="multi-channel.html">Multi-Channel Waveform</a>
      </p>
      <h2>Demo: Web Audio API</h2>
      <p>
        This demo shows how to use an
        <a href="https://www.w3.org/TR/webaudio/#AudioContext">AudioContext</a>
        to compute the waveform in the browser. Due to the memory requirements
        and processing time needed, this only works well for short duration
        audio.
      </p>
    </div>

    <div id="waveform-container">
      <div id="zoomview-container"></div>
      <div id="overview-container"></div>
    </div>

    <div id="demo-controls">
      <audio id="audio" controls="controls">
        <source src="TOL_6min_720p_download.mp3" type="audio/mpeg">
        <source src="TOL_6min_720p_download.ogg" type="audio/ogg">
        Your browser does not support the audio element.
      </audio>

      <div id="controls">
        <button data-action="zoom-in">Zoom in</button>
        <button data-action="zoom-out">Zoom out</button>
        <button data-action="add-segment">Add a Segment at current time</button>
        <button data-action="add-point">Add a Point at current time</button>
        <button data-action="log-data">Log segments/points</button>
        <input type="text" id="seek-time" value="0.0">
        <button data-action="seek">Seek</button>
      </div>
    </div>

    <div class="log">
      <div id="segments" class="hide">
        <h2>Segments</h2>
        <table>
          <thead>
            <tr>
              <th>ID</th>
              <th>Label</th>
              <th>Start time</th>
              <th>End time</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
          </tbody>
        </table>
      </div>

      <div id="points" class="hide">
        <h2>Points</h2>
        <table>
          <thead>
            <tr>
              <th>ID</th>
              <th>Label</th>
              <th>Time</th>
            </tr>
          </thead>
          <tbody>
          </tbody>
        </table>
      </div>
    </div>

    <script src="peaks.js"></script>
    <script>
      (function(Peaks) {
        var renderSegments = function(peaks) {
          var segmentsContainer = document.getElementById('segments');
          var segments = peaks.segments.getSegments();
          var html = '';

          for (var i = 0; i < segments.length; i++) {
            var segment = segments[i];

            var row = '<tr>' +
              '<td>' + segment.id + '</td>' +
              '<td>' + segment.labelText + '</td>' +
              '<td>' + segment.startTime + '</td>' +
              '<td>' + segment.endTime + '</td>' +
              '<td>' + '<a href="#' + segment.id + '" data-action="play-segment" data-id="' + segment.id + '">Play</a>' + '</td>' +
              '<td>' + '<a href="#' + segment.id + '" data-action="remove-segment" data-id="' + segment.id + '">Remove</a>' + '</td>' +
              '</tr>';

            html += row;
          }

          segmentsContainer.querySelector('tbody').innerHTML = html;

          if (html.length) {
            segmentsContainer.classList.remove('hide');
          }
        }

        var renderPoints = function(peaks) {
          var pointsContainer = document.getElementById('points');
          var points = peaks.points.getPoints();
          var html = '';

          for (var i = 0; i < points.length; i++) {
            var point = points[i];

            var row = '<tr>' +
              '<td>' + point.id + '</td>' +
              '<td>' + point.labelText + '</td>' +
              '<td>' + point.time + '</td>' +
              '<td>' + '<a href="#' + point.id + '" data-action="remove-point" data-id="' + point.id + '">Remove</a>' + '</td>' +
              '</tr>';

            html += row;
          }

          pointsContainer.querySelector('tbody').innerHTML = html;

          if (html.length) {
            pointsContainer.classList.remove('hide');
          }
        }

        var audioContext = new AudioContext();

        var audioElement = document.getElementById('audio');

        var options = {
          containers: {
            zoomview: document.getElementById('zoomview-container'),
            overview: document.getElementById('overview-container')
          },
          mediaElement: audioElement,
          webAudio: {
            audioContext: audioContext,
            scale: 128,
            multiChannel: false
          },
          keyboard: true,
          pointMarkerColor: '#006eb0',
          showPlayheadTime: true,
          zoomLevels: [128, 256, 512, 1024, 2048, 4096]
        };

        Peaks.init(options, function(err, peaksInstance) {
          console.log('Peaks instance ready');

          document.querySelector('[data-action="zoom-in"]').addEventListener('click', function() {
            peaksInstance.zoom.zoomIn();
          });

          document.querySelector('[data-action="zoom-out"]').addEventListener('click', function() {
            peaksInstance.zoom.zoomOut();
          });

          document.querySelector('button[data-action="add-segment"]').addEventListener('click', function() {
            peaksInstance.segments.add({
              startTime: peaksInstance.player.getCurrentTime(),
              endTime: peaksInstance.player.getCurrentTime() + 10,
              labelText: "Test segment",
              editable: true
            });
          });

          document.querySelector('button[data-action="add-point"]').addEventListener('click', function() {
            peaksInstance.points.add({
              time: peaksInstance.player.getCurrentTime(),
              labelText: "Test point",
              editable: true
            });
          });

          document.querySelector('button[data-action="log-data"]').addEventListener('click', function(event) {
            renderSegments(peaksInstance);
            renderPoints(peaksInstance);
          });

          document.querySelector('button[data-action="seek"]').addEventListener('click', function(event) {
            var time = document.getElementById('seek-time').value;
            var seconds = parseFloat(time);

            if (!Number.isNaN(seconds)) {
              peaksInstance.player.seek(seconds);
            }
          });

          document.querySelector('body').addEventListener('click', function(event) {
            var element = event.target;
            var action  = element.getAttribute('data-action');
            var id      = element.getAttribute('data-id');

            if (action === 'play-segment') {
              var segment = peaksInstance.segments.getSegment(id);
              peaksInstance.player.playSegment(segment);
            }
            else if (action === 'remove-point') {
              peaksInstance.points.removeById(id);
            }
            else if (action === 'remove-segment') {
              peaksInstance.segments.removeById(id);
            }
          });

          // Points mouse events

          peaksInstance.on('points.mouseenter', function(point) {
            console.log('points.mouseenter:', point);
          });

          peaksInstance.on('points.mouseleave', function(point) {
            console.log('points.mouseleave:', point);
          });

          peaksInstance.on('points.dblclick', function(point) {
            console.log('points.dblclick:', point);
          });

          peaksInstance.on('points.dragstart', function(point) {
            console.log('points.dragstart:', point);
          });

          peaksInstance.on('points.dragmove', function(point) {
            console.log('points.dragmove:', point);
          });

          peaksInstance.on('points.dragend', function(point) {
            console.log('points.dragend:', point);
          });
        });
      })(peaks);
    </script>
  </body>
</html>
